文件分块上传客户端实现

首先对文件按内容分块(有块大小的约束),然后对于每个chunk构造单独的一个UDP 数据报进行传输,在应用层的开始是自定义的包头,有块号,块长度,块指纹等元数据信息,这些信息便于接收端能够按序正确接收。

/*--vonzhou
 ---this project is to upload file after chunking using
    rabin fingerprint, here use UDP so that every packet nodelay.
    but we need to ensure the reliability.

*/

#include "global.h"

#define SERV_PORT 2500

typedef struct {
        unsigned char fp[20];
        int chunk_id;
        short flags;
        short chunk_len; // The max is 32767 enough
        char data[MAX_CHUNK_SIZE];
}TransferUnit;

// some flags for this chunk transfered.
enum{
        CHUNK_NEED_DEDU = 0x0001,   // need deduplication
        CHUNK_OTHER = 0x0002      // other for extension
};

FileInfo *fi;

int sendUDP(FileInfo *fi,int sockfd,struct sockaddr *pservaddr,socklen_t servlen){
    char buf[sizeof(TransferUnit)];
    fd_set wrset;
    struct timeval tv;
    int rlen,wlen, len = 1;
    int fd;
    int ret;
    int i,j;
    FingerChunk *p;
    TransferUnit unit;

    //connect to server
    if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)
        err_quit("connet error");
    else
        printf("connect server ok!\n");

    fd = open(fi->file_path, O_RDONLY);
    if(fd==-1)
        err_quit("fopen error %s\n",strerror(errno));

    // begin to transfer the file to the server;
    i=0;
    p = fi->first;

    while(1){
        tv.tv_sec = 1;// tell select to wait 1 second;
        tv.tv_usec = 0;

        FD_ZERO(&wrset);
        FD_SET(sockfd,&wrset);
        // wait for the socket can write
        ret = select(sockfd+1,NULL,&wrset,NULL,&tv);
        if(ret == -1)
            err_quit("select error %s\n",strerror(errno));
        else if(ret==0){
            printf("select timeout,continue circle\n");
            continue;
        }

        //prepare for writing the socket
        memset(&unit, 0, sizeof(unit));
        if(FD_ISSET(sockfd,&wrset)){
            /* we should first transfer some medadata,like filename,filter feature vector,
            *FIXME: file fingerprint to controller? to make a packetin,
            *here just let the fp = 20 1s
            */
            if(i == 0){
                for(j=0;j<20;j++)
                    unit.fp[j] = 0xff;
                unit.chunk_id = 0;
                //need not dedu
                unit.chunk_len = strlen(fi->file_path);
                wlen = write(sockfd, &unit, 28 + strlen(fi->file_path));
                if(wlen != (28 + strlen(fi->file_path)))
                     err_quit("write data to sockfd error:%s\n",strerror(errno));
                memset(&unit, 0, sizeof(unit));
            }

            if(p != NULL)
                len = p->chunklen;
            // the last read , p is null, so cannnot use p->chu
            rlen = read(fd, unit.data, len);
            if(rlen < 0)
                err_quit("fread data error %s\n",strerror(errno));
            else if(rlen==0){
                //indicate the transfer completed
                for(j=0;j<20;j++)
                    unit.fp[j] = 0xff;
                unit.chunk_id = 0;
                //need not dedu
                unit.chunk_len = 3;
                strncpy(unit.data,"end", 3);
                wlen = write(sockfd,&unit,28 + 3);
                if(wlen !=31)
                    err_quit("write end flag error:%s\n",strerror(errno));

                printf("File %s Transfer Success!\n", fi->file_path);
                close(fd);
                return 0;
            }
            // construct this tranfer unit we cannot before read
            //bcos the following p pointer used.
            for(j=0; j< 20;j++)
                unit.fp[j] = p->chunk_hash[j];// 20B fingerprint;
            unit.chunk_id = i; // 4B chunk ID
            unit.chunk_len = p->chunklen;
            unit.flags = CHUNK_NEED_DEDU;
            //write to socket
            wlen = write(sockfd, &unit, 28+p->chunklen);
            if(wlen != (rlen + 28))
                err_quit("write data to sockfd error:%s\n",strerror(errno));

            i++;
            p = p->next;
            memset(&unit, 0, sizeof(unit));
            usleep(500);
            printf("The %d times read\n",i);
        }
    }// end while(1)
}

int main(int argc ,char *argv[])
{
        char *fh;
        struct sysinfo s_info;
        long time1,time2;
        int error1,error2;
        int sockfd;
        struct stat fsize;
        struct sockaddr_in servaddr;
        error1= sysinfo(&s_info);
        time1 = s_info.uptime;
        int r;
        //  FileInfo *fi;
        fi = file_new();

        if(argc != 3)
        err_quit("useage:udpclient<IPaddress>;\n");
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family= AF_INET;
        servaddr.sin_port = htons(SERV_PORT);

        if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0)
            err_quit("[%s]is not a valid IPaddress\n",argv[1]);

        sockfd =socket(AF_INET,SOCK_DGRAM,0);

        r = fcntl(sockfd, F_GETFL, 0);
        fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK);

        // chunking file
        strcpy(fi->file_path, argv[2]);
        chunk_file(fi);
        printf("File size : %lld\n",fi->file_size);
        printf("Chunk Num : %d\n",fi->chunknum);

        sendUDP(fi, sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr));
        close(sockfd);

        fprintf(stderr,"ServerIP:\t%s\n",argv[1]);
        if(stat(argv[2],&fsize) == -1)
                perror("failed to get fiel statusi\n");
        else
                fprintf(stderr,"file name:\t%s\nfile size:\t%dK\n",argv[2],fsize.st_size/1024);
        error2=sysinfo(&s_info);
        time2 = s_info.uptime;
        printf("tranfice file time =%ld seconds\n",(time2-time1));
}

文件分块上传客户端实现

时间: 2024-08-15 11:08:41

文件分块上传客户端实现的相关文章

大文件分块上传

1.服务端SpringBoot @WebServlet(name = "vectorUpload", urlPatterns = "/gis/vectorUpload", initParams = { @WebInitParam(name = "upload_path", value = "D:\\dataTest") }) public class VectorUploadServlet extends HttpServle

JSP如何实现文件断点上传和断点下载?

核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开始. 如何分,利用强大的js库,来减轻我们的工作,市场上已经能有关于大文件分块的轮子,虽然程序员的天性曾迫使我重新造轮子.但是因为时间的关系还有工作的关系,我只能罢休了.最后我选择了百度的WebUploader来实现前端所需. 如何合,在合之前,我们还得先解决一个问题,我们如何区分分块所属那个文件的

Java web开发——文件的上传和下载

一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输.关闭浏览器后保留进度信息. 支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同. 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验:支持文件夹上传,文件夹中的文件数量达到1万个以上,且包含层级结构. 支持断点续传,关闭浏览器或刷新浏览

vue文件夹上传组件选哪个好?

一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输.关闭浏览器后保留进度信息. 支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同. 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验:支持文件夹上传,文件夹中的文件数量达到1万个以上,且包含层级结构. 支持断点续传,关闭浏览器或刷新浏览

java 大文件分片上传处理

核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开始. 如何分,利用强大的js库,来减轻我们的工作,市场上已经能有关于大文件分块的轮子,虽然程序员的天性曾迫使我重新造轮子.但是因为时间的关系还有工作的关系,我只能罢休了.最后我选择了百度的WebUploader来实现前端所需. 如何合,在合之前,我们还得先解决一个问题,我们如何区分分块所属那个文件的

【纯干货】4年前想解决的事情,今天才实验成功:浏览器原生分块上传文件

第一份软件开发工作的第一个星期(不算做试用期的一个星期,无薪水试用).因为不是软件专业,也没有经过培训和相关工作经验.老板不放心,但还是让我试一试.做的第一件事情就是上传文件,实时看进度,并且上传后预览.预览的文件类型有word,ppt,excel,flash,视频按帧获取预览图.office文件是在服务器端转成html后显示出来. 做的还满意,就留下来了,后来就在那个公司待了两年. 没解决的事情: 上传大文件,分块上传,浏览器原生不支持,需要借助第三方插件.最根本的原因就是浏览器端的js考虑的

HTML5+AJAX原生分块上传文件的关键参数设置

processData:false 这是jquery.ajax的一个参数.默认值为true,表示会将非字符串对象自动变成k1=v1&k2=v2的形式,例如一个数组参数{d:[1,2]},到服务端后会变成d[]=1&d[]=2的形式. 要将其设置为false后,才能上传ArrayBuffer对象,服务端直接从Request.InputStream获取原始字节流. w3school解释: processData 类型:Boolean 默认值: true.默认情况下,通过data选项传递进来的数

net core分块上传文件

net core分块上传文件 写完asp.net多文件上传(http://www.cnblogs.com/bestckk/p/5987383.html)后,感觉这种上传还是有很多缺陷,于是...(省略一万字,不废话).这里我没用传统的asp.net,而选择了开源的asp.net core,原因很简单,.net core是.net新的开始,更是.net和.net开发者的未来,希望.net发展越来越好(大家的工资越来越高(●ˇ?ˇ●)). 1.前端的实现: 1).html: 1 <html> 2

WebApi 文件上传,断点上传,分块上传,断点下载,查询 (图片的直接预览,视频边加载边播放)

using Manjinba.Communication.Common.Caching;using Manjinba.Communication.Common.Logging;using Manjinba.Communication.Common.Utils;using Manjinba.Communication.IRepository;using Manjinba.Communication.IService;using Manjinba.Communication.Model;using