{"action":"created","issue":{"url":"https://api.github.com/repos/NMSSH/NMSSH/issues/176","repository_url":"https://api.github.com/repos/NMSSH/NMSSH","labels_url":"https://api.github.com/repos/NMSSH/NMSSH/issues/176/labels{/name}","comments_url":"https://api.github.com/repos/NMSSH/NMSSH/issues/176/comments","events_url":"https://api.github.com/repos/NMSSH/NMSSH/issues/176/events","html_url":"https://github.com/NMSSH/NMSSH/issues/176","id":150169074,"number":176,"title":"Resume file upload","user":{"login":"Jan-E","id":1757825,"avatar_url":"https://avatars.githubusercontent.com/u/1757825?v=3","gravatar_id":"","url":"https://api.github.com/users/Jan-E","html_url":"https://github.com/Jan-E","followers_url":"https://api.github.com/users/Jan-E/followers","following_url":"https://api.github.com/users/Jan-E/following{/other_user}","gists_url":"https://api.github.com/users/Jan-E/gists{/gist_id}","starred_url":"https://api.github.com/users/Jan-E/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Jan-E/subscriptions","organizations_url":"https://api.github.com/users/Jan-E/orgs","repos_url":"https://api.github.com/users/Jan-E/repos","events_url":"https://api.github.com/users/Jan-E/events{/privacy}","received_events_url":"https://api.github.com/users/Jan-E/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-04-21T19:28:53Z","updated_at":"2016-04-22T18:21:52Z","closed_at":null,"body":"I was looking for an easy way to resume uploading of a file, when it was interrupted for some reason or another. I am using this for uploading quite large files (200-500MB) to our servers. appendContents and/or appendStream:toFileAtPath: seemed the way to achieve that, but then the application has to do a lot of calculations to get the inputstream right. I figured there should be a way to let NMSSH do the calculations.\r\n \r\nWith some experimenting I came up with new functions in NMSFTP.m (and declaration in NMSFTP.h):\r\n\r\n1. resumeFileAtPath:toFileAtPath:progress:\r\n2. resumeStream:toFileAtPath:\r\n\r\nUsage exactly the same as writeFileAtPath:toFileAtPath:progress:\r\n\r\nCould somebody review the code and tell me if I am on the right track to create a Pull Request?\r\n\r\n```\r\n- (BOOL)resumeFileAtPath:(NSString *)localPath toFileAtPath:(NSString *)path progress:(BOOL (^)(NSUInteger))progress {\r\n    return [self resumeStream:[NSInputStream inputStreamWithFileAtPath:localPath] toFileAtPath:path progress:progress];\r\n}\r\n\r\n- (BOOL)resumeStream:(NSInputStream *)inputStream toFileAtPath:(NSString *)path progress:(BOOL (^)(NSUInteger))progress {\r\n    if ([inputStream streamStatus] == NSStreamStatusNotOpen) {\r\n        [inputStream open];\r\n    }\r\n    \r\n    if (![inputStream hasBytesAvailable]) {\r\n        NMSSHLogWarn(@\"No bytes available in the stream\");\r\n        return NO;\r\n    }\r\n    \r\n    LIBSSH2_SFTP_HANDLE *handle = [self openFileAtPath:path\r\n                                                 flags:LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_READ\r\n                                                  mode:LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH];\r\n    \r\n    if (!handle) {\r\n        [inputStream close];\r\n        return NO;\r\n    }\r\n    \r\n    LIBSSH2_SFTP_ATTRIBUTES attributes;\r\n    if (libssh2_sftp_fstat(handle, &attributes) < 0) {\r\n        [inputStream close];\r\n        NMSSHLogError(@\"Unable to get attributes of file %@\", path);\r\n        return NO;\r\n    }\r\n    \r\n    libssh2_sftp_seek64(handle, attributes.filesize);\r\n    NMSSHLogVerbose(@\"Seek to position %ld of file %@\", attributes.filesize, path);\r\n    \r\n    [inputStream setProperty:[NSNumber numberWithUnsignedLongLong:attributes.filesize] forKey:NSStreamFileCurrentOffsetKey];\r\n    \r\n    BOOL success = [self writeStream:inputStream toSFTPHandle:handle progress:progress];\r\n    \r\n    libssh2_sftp_close(handle);\r\n    [inputStream close];\r\n    \r\n    return success;\r\n}\r\n\r\n```"},"comment":{"url":"https://api.github.com/repos/NMSSH/NMSSH/issues/comments/213540377","html_url":"https://github.com/NMSSH/NMSSH/issues/176#issuecomment-213540377","issue_url":"https://api.github.com/repos/NMSSH/NMSSH/issues/176","id":213540377,"user":{"login":"Jan-E","id":1757825,"avatar_url":"https://avatars.githubusercontent.com/u/1757825?v=3","gravatar_id":"","url":"https://api.github.com/users/Jan-E","html_url":"https://github.com/Jan-E","followers_url":"https://api.github.com/users/Jan-E/followers","following_url":"https://api.github.com/users/Jan-E/following{/other_user}","gists_url":"https://api.github.com/users/Jan-E/gists{/gist_id}","starred_url":"https://api.github.com/users/Jan-E/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Jan-E/subscriptions","organizations_url":"https://api.github.com/users/Jan-E/orgs","repos_url":"https://api.github.com/users/Jan-E/repos","events_url":"https://api.github.com/users/Jan-E/events{/privacy}","received_events_url":"https://api.github.com/users/Jan-E/received_events","type":"User","site_admin":false},"created_at":"2016-04-22T18:21:52Z","updated_at":"2016-04-22T18:21:52Z","body":"@Lejdborg @Frugghi I have now added this successfully to my app. The only minor inconvenience is that progress returns the number of bytes since the last resume. So I have to add up the progress values of every call to resumeFileAtPath:toFileAtPath:progress: to get the total of bytes uploaded.\r\n\r\nActually I need both values:\r\n\r\n1. the number of bytes sent in the call resumeFileAtPath to calculate an ETA\r\n2. the number of bytes sent in total = sent + attributes.filesize\r\n\r\nThe ideal solution would be to return ( NSUInteger sent , NSUInteger totalBytes ) just like copyContentsOfPath:toFileAtPath:progress: does it. But I did not yet figure out how to do that. Do you have an idea?"}}