I'm currently on a project what has to handle writing of large number of bytes to a file. I use the low-level C function
write(int, const void *, size_t)
struct stat b_stat;
blksize_t block_size = b_stat.st_blksize;
If you are "appending" to the file (each new block ends up after the previous one) you can truncate the file after the last correct block in case of error.
If you overwrite old data with new data, your only option is to use temporary file for writing and if that succeeds you rename the file with old data to some temporary name (to have a backup), rename the file with new data to the "right" name and if all of that succeeds you delete the backup of old data.